/*
 * vectorvolume.h
 *
 *  Created on: 28/08/2012
 *      Author: cvan680
 */

#ifndef VECTORVOLUME_H_
#define VECTORVOLUME_H_


#include "voreen/core/processors/volumeprocessor.h"
#include "voreen/core/ports/allports.h"
#include "voreen/core/datastructures/volume/volumeram.h"
#include "voreen/core/datastructures/volume/volume.h"
#include "voreen/core/datastructures/volume/volumecollection.h"
#include "voreen/core/datastructures/volume/volumefactory.h"
#include "voreen/core/properties/intproperty.h"
#include "voreen/core/properties/floatproperty.h"
#include "voreen/core/properties/boolproperty.h"
#include "voreen/core/properties/buttonproperty.h"

namespace voreen {

class VectorVolume : public VolumeProcessor {
public:
	VectorVolume();

    // virtual constructor
    virtual Processor* create() const;

    // documentary functions
    virtual std::string getClassName() const { return "VectorVolume";       }
    virtual std::string getCategory() const  { return "Data Generation";      }
    virtual CodeState getCodeState() const   { return CODE_STATE_EXPERIMENTAL; }

protected:

    enum VolumeType {
    	BLA = 1,
    };

    enum SingularityType {
    	NONE = 0,
    	NODE = 1,
    	SADDLE = 2,
    	ATTRACTING_FOCUS = 3,
    	REPELLING_FOCUS = 4,
    	CENTER = 5
    };

    virtual void setDescriptions() {
        setDescription("Generates a Vector Volume.");
    }

    // actual rendering code
    virtual void process();

    /// loads the shader
    virtual void initialize() throw (VoreenException);

    /// frees the shader
    virtual void deinitialize() throw (VoreenException);

    void update();

    // NEW ONES
    Volume* saddleVectorVolume();
    Volume* synthesizeVectorVolume();
    Volume* multipleSingularitiesVolume();

    tgt::vec2 calcVec(tgt::vec2 relcoords, int type);

    // TEMP method to help calculate eigenvectors
    tgt::vec2 calcEigenvector(tgt::vec2 c1, tgt::vec2 c2, bool show);

private:

    /* TODO perhaps give an interface where users can choose how many of each field-type they want,
     * 		e.g. 3 scalar fields and 2 vector fields
     */

    // this output port outputs all volumes in a collection.
    VolumePort outport;

    IntProperty prop_xdim;
    IntProperty prop_ydim;
    IntProperty prop_zdim;

    OptionProperty<SingularityType>* prop_sing1Type;
    IntProperty prop_sing1_x;
    IntProperty prop_sing1_y;

    OptionProperty<SingularityType>* prop_sing2Type;
    IntProperty prop_sing2_x;
    IntProperty prop_sing2_y;

    OptionProperty<SingularityType>* prop_sing3Type;
    IntProperty prop_sing3_x;
    IntProperty prop_sing3_y;

    OptionProperty<SingularityType>* prop_sing4Type;
    IntProperty prop_sing4_x;
    IntProperty prop_sing4_y;

    OptionProperty<SingularityType>* prop_sing5Type;
    IntProperty prop_sing5_x;
    IntProperty prop_sing5_y;

    OptionProperty<SingularityType>* prop_sing6Type;
    IntProperty prop_sing6_x;
    IntProperty prop_sing6_y;




    FloatProperty prop_decay;
    BoolProperty prop_useFirstEigenvector;

    ButtonProperty update_prop;

    VolumeFactory* volumefactory;

    Volume* volume_;

    float calculateVectorMagnitude( tgt::vec3 v );
    tgt::vec3 normalizeVector( tgt::vec3 v );

    tgt::ivec3 getDimensions();
};

} // namespace


#endif /* VECTORVOLUME_H_ */
